package SwingView.Quiz;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagLayout;

import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;

import java.awt.GridBagConstraints;
import java.awt.Insets;
import java.awt.GridLayout;

import javax.swing.JSpinner;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.swing.JCheckBox;
import javax.swing.SwingConstants;

import org.jdesktop.swingx.JXDatePicker;

import JDBC.InstructorQuizActivities;
import SwingController.CmsPresenter;
import SwingModel.CmsQuiz;
import SwingModel.CmsQuizQuestion;
import SwingView.CmsContentPanelModel;
import SwingView.CmsTimeSelector;
import SwingView.CmsWeightSelector;

import javax.swing.JButton;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.BoxLayout;

public class CmsCPQuizComposer extends CmsContentPanelModel{

	private final JLabel jlQuizComposerTitle;
	private final JPanel jpContent;
	private JTextField jtfTitle;
	private JTextArea jtfDescription;
	private JButton jbtClear;
	private JButton jbtPost;
	
	//AvaiDate:
	private JCheckBox avaiDateCB;
	private JXDatePicker avaiDatePicker;
	private CmsTimeSelector avaiTimeSelector;
	
	//DueDate:
	private JCheckBox dueDateCB;
	private JXDatePicker dueDatePicker;
	private CmsTimeSelector dueTimeSelector;
	
	//ExpDate:
	private JCheckBox expDateCB;
	private JXDatePicker expDatePicker;
	private CmsTimeSelector expTimeSelector;
	
	//Prop
	private JTextField jsPointPerQuestion;
	private JSpinner jsTime;
	private JCheckBox jcbTime;
	
	//Questions
	private JPanel jpQuestions;
	private JSpinner jsNumQuestion;
	private List<QuizQuestionComposerPanel> listOfQuestionPanel;
	private JLabel jlWeight;
	private CmsWeightSelector weightSelector;
	
	public CmsCPQuizComposer(){
		listOfQuestionPanel = new ArrayList();
		
		//helper panel to center the title panel
		JPanel jp = new JPanel();
		jp.setPreferredSize(new Dimension(650, 65));
		jp.setOpaque(false);
		jp.setBorder(BorderFactory.createEmptyBorder());
		GridBagLayout gbl_jp = new GridBagLayout();
		jp.setLayout(gbl_jp);
		
		//content panel
		jpContent = new JPanel();
		GridBagLayout gbl_jpContent = new GridBagLayout();
		jpContent.setLayout(gbl_jpContent);
		jpContent.setOpaque(false);

		//Set up the scroll bar
		JScrollPane scroll = new JScrollPane(jpContent);
		
		//_________________________________________________________
		//TITLE:
		JPanel jpTitle = new JPanel();
		jpTitle.setOpaque(false);
		jpTitle.setPreferredSize(new Dimension(550,30));
		jpTitle.setMinimumSize(new Dimension(550,30));
		GridBagConstraints gbc_jpTitle = new GridBagConstraints();
		gbc_jpTitle.insets = new Insets(0, 0, 5, 0);
		gbc_jpTitle.fill = GridBagConstraints.HORIZONTAL;
		gbc_jpTitle.gridx = 0;
		gbc_jpTitle.gridy = 0;
		jpContent.add(jpTitle, gbc_jpTitle);
		GridBagLayout gbl_jpTitle = new GridBagLayout();
		jpTitle.setLayout(gbl_jpTitle);
		
		JLabel jlTitle = new JLabel("Title: ");
		jlTitle.setFont(new Font("Lucida Grande", Font.BOLD, 13));
		GridBagConstraints gbc_jlTitle = new GridBagConstraints();
		gbc_jlTitle.weightx = 1.0;
		gbc_jlTitle.anchor = GridBagConstraints.FIRST_LINE_START;
		gbc_jlTitle.insets = new Insets(0, 0, 0, 5);
		gbc_jlTitle.gridx = 0;
		gbc_jlTitle.gridy = 0;
		jpTitle.add(jlTitle, gbc_jlTitle);
		
		jtfTitle = new JTextField();
		jtfTitle.setToolTipText("Please enter the quiz title");
		jtfTitle.setBorder(BorderFactory.createLineBorder(Color.GRAY));
		jtfTitle.setMinimumSize(new Dimension(430,20));
		jtfTitle.setPreferredSize(new Dimension(430,20));
		GridBagConstraints gbc_jtfTitle = new GridBagConstraints();
		gbc_jtfTitle.anchor = GridBagConstraints.FIRST_LINE_END;
		gbc_jtfTitle.gridx = 1;
		gbc_jtfTitle.gridy = 0;
		jpTitle.add(jtfTitle, gbc_jtfTitle);
		
		//_________________________________________________________
		//DESCRIPTION:
		JPanel jpDescription = new JPanel();
		jpDescription.setPreferredSize(new Dimension(550, 100));
		jpDescription.setMinimumSize(new Dimension(550, 100));
		GridBagLayout gbl_jpDescription = new GridBagLayout();
		gbl_jpDescription.rowWeights = new double[]{0.0};
		gbl_jpDescription.columnWeights = new double[]{1.0, 0.0};
		jpDescription.setLayout(gbl_jpDescription);
		jpDescription.setOpaque(false);
		GridBagConstraints gbc_jpDescription = new GridBagConstraints();
		gbc_jpDescription.insets = new Insets(0, 0, 5, 0);
		gbc_jpDescription.fill = GridBagConstraints.HORIZONTAL;
		gbc_jpDescription.gridx = 0;
		gbc_jpDescription.gridy = 1;
		jpContent.add(jpDescription, gbc_jpDescription);
		
		JLabel jlDescription = new JLabel("Description: ");
		jlDescription.setFont(new Font("Lucida Grande", Font.BOLD, 13));
		GridBagConstraints gbc_jlDescription = new GridBagConstraints();
		gbc_jlDescription.insets = new Insets(0, 0, 5, 5);
		gbc_jlDescription.anchor = GridBagConstraints.FIRST_LINE_START;
		gbc_jlDescription.gridx = 0;
		gbc_jlDescription.gridy = 0;
		gbc_jlDescription.weightx = 1.0;
		jpDescription.add(jlDescription, gbc_jlDescription);
		
		jtfDescription = new JTextArea();
		jtfDescription.setLineWrap(true);
		jtfDescription.setWrapStyleWord(true);
		
		JScrollPane jspDescription = new JScrollPane(jtfDescription);
		jspDescription.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
		jspDescription.setPreferredSize(new Dimension(430,90));
		GridBagConstraints gbc_jspDescription = new GridBagConstraints();
		gbc_jspDescription.insets = new Insets(0, 0, 5, 0);
		gbc_jspDescription.fill = GridBagConstraints.BOTH;
		gbc_jspDescription.gridx = 1;
		gbc_jspDescription.gridy = 0;
		jpDescription.add(jspDescription, gbc_jspDescription);
		//_________________________________________________________
		//AVAI DATE:
		JLabel lblAvailableDate = new JLabel("Available Date:");
		lblAvailableDate.setFont(new Font("Lucida Grande", Font.BOLD, 13));
		GridBagConstraints gbc_lblAvailableDate = new GridBagConstraints();
		gbc_lblAvailableDate.fill = GridBagConstraints.HORIZONTAL;
		gbc_lblAvailableDate.insets = new Insets(0, 0, 5, 0);
		gbc_lblAvailableDate.gridx = 0;
		gbc_lblAvailableDate.gridy = 2;
		jpContent.add(lblAvailableDate, gbc_lblAvailableDate);
		
		JPanel jpAvaiDate = new JPanel();
		jpAvaiDate.setOpaque(false);
		FlowLayout fl_jpAvaiDate = (FlowLayout) jpAvaiDate.getLayout();
		fl_jpAvaiDate.setVgap(0);
		fl_jpAvaiDate.setAlignment(FlowLayout.LEFT);
		GridBagConstraints gbc_jpAvaiDate = new GridBagConstraints();
		gbc_jpAvaiDate.insets = new Insets(0, 0, 5, 0);
		gbc_jpAvaiDate.fill = GridBagConstraints.BOTH;
		gbc_jpAvaiDate.gridx = 0;
		gbc_jpAvaiDate.gridy = 3;
		jpContent.add(jpAvaiDate, gbc_jpAvaiDate);
		
		avaiDateCB = new JCheckBox("");
		avaiDateCB.setSelected(true);
		jpAvaiDate.add(avaiDateCB);
		
		avaiDatePicker = new JXDatePicker();
		avaiDatePicker.setDate(new Date());
		jpAvaiDate.add(avaiDatePicker);
		
		avaiTimeSelector = new CmsTimeSelector();
		jpAvaiDate.add(avaiTimeSelector);
		
		//_________________________________________________________
		//DUE DATE:
		JLabel lblDueDate = new JLabel("Due Date:");
		lblDueDate.setFont(new Font("Lucida Grande", Font.BOLD, 13));
		GridBagConstraints gbc_lblDueDate = new GridBagConstraints();
		gbc_lblDueDate.fill = GridBagConstraints.HORIZONTAL;
		gbc_lblDueDate.insets = new Insets(0, 0, 5, 0);
		gbc_lblDueDate.gridx = 0;
		gbc_lblDueDate.gridy = 4;
		jpContent.add(lblDueDate, gbc_lblDueDate);
		
		JPanel jpDueDate = new JPanel();
		jpDueDate.setOpaque(false);
		FlowLayout fl_jpDueDate = (FlowLayout) jpDueDate.getLayout();
		fl_jpDueDate.setVgap(0);
		fl_jpDueDate.setAlignment(FlowLayout.LEFT);
		GridBagConstraints gbc_jpDueDate = new GridBagConstraints();
		gbc_jpDueDate.insets = new Insets(0, 0, 5, 0);
		gbc_jpDueDate.fill = GridBagConstraints.BOTH;
		gbc_jpDueDate.gridx = 0;
		gbc_jpDueDate.gridy = 5;
		jpContent.add(jpDueDate, gbc_jpDueDate);
		
		dueDateCB = new JCheckBox("");
		dueDateCB.setSelected(true);
		dueDateCB.setEnabled(false);
		jpDueDate.add(dueDateCB);
		
		dueDatePicker = new JXDatePicker();
		dueDatePicker.setDate( new Date((new Date()).getTime() + 7 * 24 * 60 * 60 * 1000)); //Default to be a week from now
		jpDueDate.add(dueDatePicker);
		
		dueTimeSelector = new CmsTimeSelector();
		jpDueDate.add(dueTimeSelector);
		
		//_________________________________________________________
		//EXP DATE:
		JLabel lblExpirationDate = new JLabel("Expiration Date: ");
		lblExpirationDate.setFont(new Font("Lucida Grande", Font.BOLD, 13));
		GridBagConstraints gbc_lblExpirationDate = new GridBagConstraints();
		gbc_lblExpirationDate.fill = GridBagConstraints.HORIZONTAL;
		gbc_lblExpirationDate.insets = new Insets(0, 0, 5, 0);
		gbc_lblExpirationDate.gridx = 0;
		gbc_lblExpirationDate.gridy = 6;
		jpContent.add(lblExpirationDate, gbc_lblExpirationDate);
		
		JPanel jpExpDate = new JPanel();
		jpExpDate.setOpaque(false);
		FlowLayout flowLayout = (FlowLayout) jpExpDate.getLayout();
		flowLayout.setAlignment(FlowLayout.LEFT);
		GridBagConstraints gbc_jpExpDate = new GridBagConstraints();
		gbc_jpExpDate.insets = new Insets(0, 0, 5, 0);
		gbc_jpExpDate.fill = GridBagConstraints.BOTH;
		gbc_jpExpDate.gridx = 0;
		gbc_jpExpDate.gridy = 7;
		jpContent.add(jpExpDate, gbc_jpExpDate);
		
		expDateCB = new JCheckBox();
		expDateCB.setSelected(false);
		jpExpDate.add(expDateCB);
		
		expDatePicker = new JXDatePicker();
		expDatePicker.setDate(new Date(CmsPresenter.END_OF_SEMESTER.getTime()));
		expDatePicker.setEnabled(false);
		jpExpDate.add(expDatePicker);
		
		expTimeSelector = new CmsTimeSelector();
		expTimeSelector.setEnabled(false);
		jpExpDate.add(expTimeSelector);
		
		//_________________________________________________________
		//PROPERTIES:
		JPanel jpProp = new JPanel();
		jpProp.setOpaque(false);
		GridBagConstraints gbc_jpProp = new GridBagConstraints();
		gbc_jpProp.insets = new Insets(0, 0, 5, 0);
		gbc_jpProp.fill = GridBagConstraints.HORIZONTAL;
		gbc_jpProp.gridx = 0;
		gbc_jpProp.gridy = 8;
		jpContent.add(jpProp, gbc_jpProp);
		GridBagLayout gbl_jpProp = new GridBagLayout();
		gbl_jpProp.rowWeights = new double[]{1.0, 0.0};
		gbl_jpProp.columnWeights = new double[]{0.0, 1.0, 0.0, 0.0, 0.0, 0.0};
		jpProp.setLayout(gbl_jpProp);
		
		JLabel lblWeight = new JLabel("Percent Weight: ");
		lblWeight.setFont(new Font("Lucida Grande", Font.BOLD, 13));
		GridBagConstraints gbc_jlWeight = new GridBagConstraints();
		gbc_jlWeight.anchor = GridBagConstraints.LINE_START;
		gbc_jlWeight.fill = GridBagConstraints.HORIZONTAL;
		gbc_jlWeight.insets = new Insets(0, 0, 5, 5);
		gbc_jlWeight.gridx = 0;
		gbc_jlWeight.gridy = 0;
		jpProp.add(lblWeight, gbc_jlWeight);
		
		SpinnerNumberModel weightModel = new SpinnerNumberModel(10.0,0,100,1.0);
		
		weightSelector = new CmsWeightSelector();
		GridBagConstraints gbc_panel = new GridBagConstraints();
		gbc_panel.insets = new Insets(0, 0, 5, 5);
		gbc_panel.fill = GridBagConstraints.BOTH;
		gbc_panel.gridx = 1;
		gbc_panel.gridy = 0;
		jpProp.add(weightSelector, gbc_panel);
		
		jcbTime = new JCheckBox("");
		jcbTime.setHorizontalAlignment(SwingConstants.RIGHT);
		jcbTime.setVerticalAlignment(SwingConstants.TOP);
		GridBagConstraints gbc_jcbTime = new GridBagConstraints();
		gbc_jcbTime.weightx = 0.15;
		gbc_jcbTime.anchor = GridBagConstraints.FIRST_LINE_END;
		gbc_jcbTime.fill = GridBagConstraints.HORIZONTAL;
		gbc_jcbTime.insets = new Insets(0, 0, 5, 5);
		gbc_jcbTime.gridx = 2;
		gbc_jcbTime.gridy = 0;
		jpProp.add(jcbTime, gbc_jcbTime);
		
		
		jsTime = new JSpinner(new SpinnerNumberModel(30,1,200,1));
		jsTime.setToolTipText("Please select time constraint for the quiz");
		jsTime.setPreferredSize(new Dimension(60,23));
		jsTime.setEnabled(false);
		GridBagConstraints gbc_jsTime = new GridBagConstraints();
		gbc_jsTime.anchor = GridBagConstraints.FIRST_LINE_START;
		gbc_jsTime.insets = new Insets(0, 0, 5, 5);
		gbc_jsTime.gridx = 4;
		gbc_jsTime.gridy = 0;
		jpProp.add(jsTime, gbc_jsTime);
		
		JLabel lblminutes = new JLabel("  (minutes)");
		GridBagConstraints gbc_lblminutes = new GridBagConstraints();
		gbc_lblminutes.anchor = GridBagConstraints.LINE_START;
		gbc_lblminutes.insets = new Insets(0, 0, 5, 0);
		gbc_lblminutes.gridx = 5;
		gbc_lblminutes.gridy = 0;
		jpProp.add(lblminutes, gbc_lblminutes);
		
		JLabel lblNumberOfQuestions = new JLabel("Number Of Questions: ");
		lblNumberOfQuestions.setFont(new Font("Lucida Grande", Font.BOLD, 13));
		GridBagConstraints gbc_lblNumberOfQuestions = new GridBagConstraints();
		gbc_lblNumberOfQuestions.fill = GridBagConstraints.HORIZONTAL;
		gbc_lblNumberOfQuestions.anchor = GridBagConstraints.LINE_START;
		gbc_lblNumberOfQuestions.insets = new Insets(0, 0, 0, 5);
		gbc_lblNumberOfQuestions.gridx = 0;
		gbc_lblNumberOfQuestions.gridy = 1;
		jpProp.add(lblNumberOfQuestions, gbc_lblNumberOfQuestions);
		
		JLabel lblTimeConstraint = new JLabel("Time Constraint: ");
		lblTimeConstraint.setFont(new Font("Lucida Grande", Font.BOLD, 13));
		GridBagConstraints gbc_lblTimeConstraint = new GridBagConstraints();
		gbc_lblTimeConstraint.anchor = GridBagConstraints.LINE_END;
		gbc_lblTimeConstraint.insets = new Insets(0, 0, 5, 5);
		gbc_lblTimeConstraint.gridx = 3;
		gbc_lblTimeConstraint.gridy = 0;
		jpProp.add(lblTimeConstraint, gbc_lblTimeConstraint);
		
		jsNumQuestion = new JSpinner(new SpinnerNumberModel(0,0,100,1));
		jsNumQuestion.setPreferredSize(new Dimension(60,23));
		
		GridBagConstraints gbc_jsNumQuestion = new GridBagConstraints();
		gbc_jsNumQuestion.anchor = GridBagConstraints.LINE_START;
		gbc_jsNumQuestion.insets = new Insets(0, 0, 0, 5);
		gbc_jsNumQuestion.gridx = 1;
		gbc_jsNumQuestion.gridy = 1;
		jpProp.add(jsNumQuestion, gbc_jsNumQuestion);
		
		JLabel lblPointPerQuestions = new JLabel("Point Per Questions: ");
		lblPointPerQuestions.setFont(new Font("Lucida Grande", Font.BOLD, 13));
		GridBagConstraints gbc_lblPointPerQuestions = new GridBagConstraints();
		gbc_lblPointPerQuestions.gridwidth = 2;
		gbc_lblPointPerQuestions.weightx = 0.2;
		gbc_lblPointPerQuestions.anchor = GridBagConstraints.EAST;
		gbc_lblPointPerQuestions.insets = new Insets(0, 0, 0, 5);
		gbc_lblPointPerQuestions.gridx = 2;
		gbc_lblPointPerQuestions.gridy = 1;
		jpProp.add(lblPointPerQuestions, gbc_lblPointPerQuestions);
		
		jsPointPerQuestion = new JTextField();
		jsPointPerQuestion.setPreferredSize(new Dimension(60,23));
		jsPointPerQuestion.setEditable(false);
		GridBagConstraints gbc_jsPointPerQuestion = new GridBagConstraints();
		gbc_jsPointPerQuestion.gridwidth = 2;
		gbc_jsPointPerQuestion.anchor = GridBagConstraints.FIRST_LINE_START;
		gbc_jsPointPerQuestion.weightx = 0.5;
		gbc_jsPointPerQuestion.gridx = 4;
		gbc_jsPointPerQuestion.gridy = 1;
		jpProp.add(jsPointPerQuestion, gbc_jsPointPerQuestion);
		
		
		//_________________________________________________________
		//QUESTION:
		JPanel jpQ = new JPanel();
		jpQ.setOpaque(false);
		GridBagConstraints gbc_jpQ = new GridBagConstraints();
		gbc_jpQ.fill = GridBagConstraints.HORIZONTAL;
		gbc_jpQ.gridx = 0;
		gbc_jpQ.gridy = 9;
		jpContent.add(jpQ, gbc_jpQ);
		GridBagLayout gbl_jpQ = new GridBagLayout();
		jpQ.setLayout(gbl_jpQ);
		
		//Question Label
		JLabel lblQuestions = new JLabel("Questions:");
		lblQuestions.setFont(new Font("Lucida Grande", Font.BOLD, 15));
		GridBagConstraints gbc_lblQuestions = new GridBagConstraints();
		gbc_lblQuestions.insets = new Insets(0, 0, 10, 0);
		gbc_lblQuestions.weightx = 0.05;
		gbc_lblQuestions.fill = GridBagConstraints.HORIZONTAL;
		gbc_lblQuestions.anchor = GridBagConstraints.FIRST_LINE_START;
		gbc_lblQuestions.gridx = 0;
		gbc_lblQuestions.gridy = 0;
		jpQ.add(lblQuestions, gbc_lblQuestions);
		
		//Add Question button
		JButton jbtAddQuestion = new JButton("+ Add Question");
		
		jbtAddQuestion.setOpaque(false);
		jbtAddQuestion.setBorder(BorderFactory.createEmptyBorder());
		jbtAddQuestion.setFont(new Font("Lucida Grande", Font.BOLD, 13));
		jbtAddQuestion.setForeground(Color.BLUE);
		GridBagConstraints gbc_jbtAddQuestion = new GridBagConstraints();
		gbc_jbtAddQuestion.weightx = 0.5;
		gbc_jbtAddQuestion.anchor = GridBagConstraints.FIRST_LINE_START;
		gbc_jbtAddQuestion.gridx = 1;
		gbc_jbtAddQuestion.gridy = 0;
		jpQ.add(jbtAddQuestion, gbc_jbtAddQuestion);
		
		//remove question button
		jpQuestions = new JPanel();
		jpQuestions.setOpaque(false);
		GridBagConstraints gbc_jpQuestions = new GridBagConstraints();
		gbc_jpQuestions.weighty = 1.0;
		gbc_jpQuestions.fill = GridBagConstraints.HORIZONTAL;
		gbc_jpQuestions.gridx = 0;
		gbc_jpQuestions.gridy = 10;
		jpContent.add(jpQuestions, gbc_jpQuestions);
		jpQuestions.setLayout(new GridBagLayout());
		GridBagConstraints c = new GridBagConstraints();
		jpQuestions.add(new JLabel("<<Please add questions>>"),c);
		
		
		//main Scroll bar
		scroll.setBorder(BorderFactory.createEmptyBorder());
		scroll.setOpaque(true);
		scroll.setPreferredSize(new Dimension(650,450));
		scroll.setBackground(Color.WHITE);

		//set up student people panel and add components
		setLayout(new BorderLayout());
		add(jp,BorderLayout.NORTH);//Add title People
		
		//instantiate People title
		jlQuizComposerTitle = new JLabel("Quiz Composer");
		jlQuizComposerTitle.setFont(jlQuizComposerTitle.getFont().deriveFont(20.0f).deriveFont(Font.BOLD));
		jlQuizComposerTitle.setBorder(BorderFactory.createEmptyBorder(0, 8, 10, 8));
		GridBagConstraints gbc_jlQuizComposerTitle = new GridBagConstraints();
		gbc_jlQuizComposerTitle.gridwidth = 2;
		gbc_jlQuizComposerTitle.gridx = 0;
		gbc_jlQuizComposerTitle.gridy = 0;
		jp.add(jlQuizComposerTitle, gbc_jlQuizComposerTitle);
		
		jbtClear = new JButton("Clear Everything");
		jbtClear.setFont(jbtClear.getFont().deriveFont(Font.BOLD).deriveFont(13.0f));
		jbtClear.setPreferredSize(new Dimension(140, 20));
		jbtClear.setMinimumSize(new Dimension(75,20));
		jbtClear.setBackground(new Color(170,170,170));
		jbtClear.setForeground(new Color(30,30,30));
		jbtClear.setOpaque(true);
		jbtClear.setBorder(BorderFactory.createLineBorder(new Color(30,30,30)));
		GridBagConstraints gbc_jbtClear = new GridBagConstraints();
		gbc_jbtClear.insets = new Insets(0, 0, 0, 20);
		gbc_jbtClear.gridx = 0;
		gbc_jbtClear.gridy = 1;
		jp.add(jbtClear, gbc_jbtClear);
		
		jbtPost = new JButton("Post");
		jbtPost.setFont(jbtPost.getFont().deriveFont(Font.BOLD).deriveFont(13.0f));
		jbtPost.setPreferredSize(new Dimension(70, 20));
		jbtPost.setMinimumSize(new Dimension(75,20));
		jbtPost.setBackground(new Color(170,170,170));
		jbtPost.setForeground(new Color(30,30,30));
		jbtPost.setOpaque(true);
		jbtPost.setBorder(BorderFactory.createLineBorder(new Color(30,30,30)));
		GridBagConstraints gbc_jbtPost = new GridBagConstraints();
		gbc_jbtPost.insets = new Insets(0, 20, 0, 0);
		gbc_jbtPost.gridx = 1;
		gbc_jbtPost.gridy = 1;
		jp.add(jbtPost, gbc_jbtPost);
		add(scroll,BorderLayout.WEST);//Add People List
		
		
		//ACTION LISTENERS:
		jsNumQuestion.addChangeListener(new NumQuestionChangeListener());
		jbtAddQuestion.addActionListener(new AddQuestionActionListener());
		
		//Time checkBox action listener:
		jcbTime.addChangeListener(new ChangeListener(){

			@Override
			public void stateChanged(ChangeEvent e) {
				if (jcbTime.isSelected()){
					jsTime.setEnabled(true);
				}
				else jsTime.setEnabled(false);
			}
			
		});
		
		//AvaiDate Checkbox action listener:
		avaiDateCB.addChangeListener(new ChangeListener(){

			@Override
			public void stateChanged(ChangeEvent e) {
				if(avaiDateCB.isSelected()){
					avaiDatePicker.setEnabled(true);
					avaiTimeSelector.setEnabled(true);
				}
				else{
					avaiDatePicker.setEnabled(false);
					avaiTimeSelector.setEnabled(false);
				}
			}
			
		});
		
		//AvaiDate value Check
		avaiDatePicker.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				validateDateInput();
			}
			
		});
		
		//AvaiDate value Check
		avaiDatePicker.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				validateDateInput();
			}
			
		});
		
		//avai TimeSelector value check
		avaiTimeSelector.addItemListener(new ItemListener(){
			@Override
			public void itemStateChanged(ItemEvent e) {
				validateDateInput();
			}
		});
		
		//Due Checkbox action listener:
		dueDateCB.addChangeListener(new ChangeListener(){

			@Override
			public void stateChanged(ChangeEvent e) {
				if(dueDateCB.isSelected()){
					dueDatePicker.setEnabled(true);
					dueTimeSelector.setEnabled(true);
				}
				else{
					dueDatePicker.setEnabled(false);
					dueTimeSelector.setEnabled(false);
				}
			}
			
		});
		
		//DueDate value Check
		dueDatePicker.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				validateDateInput();
			}
			
		});
		
		//due TimeSelector value check
		dueTimeSelector.addItemListener(new ItemListener(){
			@Override
			public void itemStateChanged(ItemEvent e) {
				validateDateInput();
			}
		});
		
		//Exp Checkbox action listener:
		expDateCB.addChangeListener(new ChangeListener(){

			@Override
			public void stateChanged(ChangeEvent e) {
				if(expDateCB.isSelected()){
					expDatePicker.setEnabled(true);
					expTimeSelector.setEnabled(true);
				}
				else{
					expDatePicker.setEnabled(false);
					expTimeSelector.setEnabled(false);
				}
			}
			
		});
		
		//ExpDate value Check
		expDatePicker.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				validateDateInput();
			}
			
		});
		
		//exp TimeSelector value check
		expTimeSelector.addItemListener(new ItemListener(){
			@Override
			public void itemStateChanged(ItemEvent e) {
				validateDateInput();
			}
		});
		
		//clear action listner
		jbtClear.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent e) {
				int value = JOptionPane.showConfirmDialog(CmsPresenter.mainView, "Do you want to clear all of your inputs?",
															"WARNING", JOptionPane.WARNING_MESSAGE);
				
				if(value==JOptionPane.YES_OPTION) clearAllInput();
			}
			
		});
		
		//post action listener
		jbtPost.addActionListener(new ALQuizPost());
		
		
	}
	
	private void displayListOfQuestion(){
		jpQuestions.removeAll();
		for(int i=0; i < listOfQuestionPanel.size(); i++){
			GridBagConstraints c = new GridBagConstraints();
			c.gridy = i;
			listOfQuestionPanel.get(i).setQuestionNumber(i+1); //Set question number
			jpQuestions.add(listOfQuestionPanel.get(i),c); //add to panel for displaying
			System.out.println(i);
		}
		jpQuestions.revalidate();
	}
	
	public Date getSelectedAvaiDate(){
		Date avaiDate;
		
		if(avaiDateCB.isSelected()){
			long dayMilis = avaiDatePicker.getDate().getTime();
			long timeMilis = avaiTimeSelector.getHour() * 60 * 60 * 1000 //milisecond = hour * 60min * 60sec * 1000milis
					+ avaiTimeSelector.getMinute() * 60 * 1000;//milisecond = min * 60sec * 1000milis
			avaiDate = new Date(dayMilis + timeMilis);
		}
		else avaiDate = new Date(CmsPresenter.DEFAULT_AVAI_DATE.getTime());
		
		return avaiDate;	
	}
	
	public Date getSelectedExpDate(){
		Date expDate;
		
		if(this.expDateCB.isSelected()){
			long dayMilis = expDatePicker.getDate().getTime();
			long timeMilis = expTimeSelector.getHour() * 60 * 60 * 1000 //milisecond = hour * 60min * 60sec * 1000milis
					+ expTimeSelector.getMinute() * 60 * 1000;//milisecond = min * 60sec * 1000milis
			expDate = new Date(dayMilis + timeMilis);
		}
		else expDate = new Date(CmsPresenter.DEFAULT_EXP_DATE.getTime());
		
		return expDate;
	}
	
	public Date getSelectedDueDate(){
		Date dueDate;
		
		if(this.dueDateCB.isSelected()){
			long dayMilis = dueDatePicker.getDate().getTime();
			long timeMilis = dueTimeSelector.getHour() * 60 * 60 * 1000 //milisecond = hour * 60min * 60sec * 1000milis
					+ dueTimeSelector.getMinute() * 60 * 1000;//milisecond = min * 60sec * 1000milis
			dueDate = new Date(dayMilis + timeMilis);
		}
		else dueDate = new Date(CmsPresenter.DEFAULT_EXP_DATE.getTime());
		
		return dueDate;
	}
	
	public String getTitle(){
		return jtfTitle.getText();
	}
	
	public String getDescription(){
		return jtfDescription.getText();
	}
	
	public double getWeight(){
		return weightSelector.getWeight();
	}
	
	public int getTimeConstraint(){
		if(jcbTime.isSelected()) return (Integer) jsTime.getValue();
		else return 0;
	}
	
	public CmsQuiz getComposedQuiz(){
		int quizID = 0;
		String quizTitle = getTitle();
		String quizDescription = getDescription();
		double maxPoint = getNumberOfQuestion();
		double percentWeight = getWeight();
		Date createdDate = new Date();
		Date avaiDate = this.getSelectedAvaiDate();
		Date dueDate = this.getSelectedDueDate();
		Date expDate = this.getSelectedExpDate();
		int duration = this.getTimeConstraint();
		boolean hasTaken = false;
		List<CmsQuizQuestion> questions = new ArrayList();
		for(QuizQuestionComposerPanel q : listOfQuestionPanel){
			questions.add(q.getSelectedQuizQuestion());
		}
		return new CmsQuiz(duration, quizTitle, quizDescription, maxPoint, percentWeight, createdDate, avaiDate, dueDate, expDate, duration, questions, hasTaken);
	}
	
	public int getNumberOfQuestion(){
		return listOfQuestionPanel.size();
	}
	
	public void clearAllInput(){
		jtfTitle.setText("");
		jtfDescription.setText("");
		avaiDatePicker.setDate(new Date());
		avaiTimeSelector.setTime(0, 0);
		dueDatePicker.setDate( new Date((new Date()).getTime() + 7 * 24 * 60 * 60 * 1000));
		expDateCB.setSelected(false);
		expDatePicker.setDate(new Date(CmsPresenter.END_OF_SEMESTER.getTime()));
		expTimeSelector.setTime(0, 0);;
		jsTime.setValue(new Integer(30));
		weightSelector.reset();
		
		for(QuizQuestionComposerPanel q : listOfQuestionPanel){
			q.clearContent();
		}
		jsNumQuestion.setValue(new Integer(0));
	}
	
	public boolean validateAllInput(){
		if(validateTitleInput() & validateDateInput()){
			if(validateQuestionInput()){ 
				if(weightSelector.getWeight() == 0.0){
					int returnVal = JOptionPane.showConfirmDialog(CmsPresenter.mainView, "The percent weight for this quiz is 0.0%.\nDo you want to continue posting this quiz?");
					if(returnVal == JOptionPane.YES_OPTION) return true;
					else return false;
				}
				else return true;
			}
			else return false;
		}
		return false;
	}
	
	public boolean validateDateInput(){
		Date avaiDate = new Date(getSelectedAvaiDate().getTime());
		Date dueDate = new Date(getSelectedDueDate().getTime());
		Date expDate = new Date(getSelectedExpDate().getTime());
		Date latestStartTime = new Date(getSelectedAvaiDate().getTime() 
										+ ( getTimeConstraint() )* 60 * 1000);
		if (latestStartTime.compareTo(dueDate) > 0 && getTimeConstraint() > 0){
			JOptionPane.showMessageDialog(CmsPresenter.mainView,
										"The latest start time with current selected due date and time constraint is: " 
										+ CmsPresenter.sdf.format(latestStartTime) + "\n"
										+ "The available Date must be before the latest start time." 
										+ "Please adjust the available date or the due date accordingly.",
										"ERROR!",
										JOptionPane.ERROR_MESSAGE);
			return false;
		}
		else if(latestStartTime.compareTo(dueDate) > 0 && getTimeConstraint() == 0){
			JOptionPane.showMessageDialog(CmsPresenter.mainView,
				    "The available Date and Time have to be before the due Date and Time!",
				    "ERROR!",
				    JOptionPane.ERROR_MESSAGE);
			return false;
		}
		else if(dueDate.compareTo(expDate) >= 0){
			JOptionPane.showMessageDialog(CmsPresenter.mainView,
				    "The due Date and Time have to be before the expiration Date and Time!",
				    "ERROR!",
				    JOptionPane.ERROR_MESSAGE);
			return false;
		}
		else if(dueDate.compareTo(new Date()) <= 0){
			JOptionPane.showMessageDialog(CmsPresenter.mainView,
				    "Due Date has to be before today",
				    "ERROR!",
				    JOptionPane.ERROR_MESSAGE);
			return false;
		}
		else if(expDate.compareTo(new Date()) <= 0){
			JOptionPane.showMessageDialog(CmsPresenter.mainView,
				    "Exp Date has to be before today",
				    "ERROR!",
				    JOptionPane.ERROR_MESSAGE);
			return false;
		}
		else return true;
	}
	
	public boolean validateTitleInput(){
		if(jtfTitle.getText().trim().equals("")){
			JOptionPane.showMessageDialog(CmsPresenter.mainView,
				    "Please input a Title for the Quiz!",
				    "ERROR!",
				    JOptionPane.ERROR_MESSAGE);
			return false;
		}
		
		List<CmsQuiz> quizzes = InstructorQuizActivities.getListOfQuiz(CmsPresenter.user.getSelectedCourse().getCourseID());
		for(CmsQuiz quiz: quizzes){
			if(jtfTitle.getText().trim().toLowerCase().equals(quiz.getQuizTitle().toLowerCase())){
				JOptionPane.showMessageDialog(CmsPresenter.mainView,
					    "This quiz title has already been used on a quiz you created!\n Please enter a different title.",
					    "ERROR!",
					    JOptionPane.ERROR_MESSAGE);
				return false;
			}
		}
	
		return true;
	}
	
	public boolean validateQuestionInput(){
		if(listOfQuestionPanel.size() == 0){
			int value = JOptionPane.showConfirmDialog(CmsPresenter.mainView,
				    "There are no questions for this Quiz. Do you want to continue posting the quiz?",
				    "WARNING!",
				    JOptionPane.WARNING_MESSAGE);
			if(value == JOptionPane.YES_OPTION) return true;
			else return false;
		}
		else {
			boolean validateResult = true;
			
			//MISSING QUESTION
			StringBuilder missingQuestionError = new StringBuilder();
			missingQuestionError.append("Cannot proceed to post this quiz! \nThe following questions are missing the question:\n\n");
			for(QuizQuestionComposerPanel question : listOfQuestionPanel){
				if(question.validateMissingQuestion() == false){
					missingQuestionError.append("   - Question #"+ question.questionIndex + "\n");
					validateResult = false;
				}
			}
			missingQuestionError.append("\nPlease enter the question for those questions.");
			if(validateResult == false){
				JOptionPane.showMessageDialog(CmsPresenter.mainView, missingQuestionError.toString(), "ERROR!", JOptionPane.ERROR_MESSAGE);
				return false;
			}
			
			//MISSING ALL OPTION:
			StringBuilder missingAllOption = new StringBuilder();
			missingAllOption.append("Cannot proceed to post this quiz! \nThe following questions are missing the options:\n\n");
			for(QuizQuestionComposerPanel question : listOfQuestionPanel){
				if(question.validateMissingAllOptions() == false){
					missingAllOption.append("   - Question #"+ question.questionIndex + "\n");
					validateResult = false;
				}
			}
			missingAllOption.append("\nPlease enter the options for those questions.");
			if(validateResult == false){
				JOptionPane.showMessageDialog(CmsPresenter.mainView, missingAllOption.toString(), "ERROR!", JOptionPane.ERROR_MESSAGE);
				return false;
			}
			
			//SAME OPTION:
			StringBuilder sameOption = new StringBuilder();
			sameOption.append("Cannot proceed to post this quiz! \nThe following questions have repeated options:\n\n");
			for(QuizQuestionComposerPanel question : listOfQuestionPanel){
				if(question.validateSameOptionContent() == false){
					sameOption.append("   - Question #"+ question.questionIndex + "\n");
					validateResult = false;
				}
			}
			sameOption.append("\nPlease remove the repeated options.");
			if(validateResult == false){
				JOptionPane.showMessageDialog(CmsPresenter.mainView, sameOption.toString(), "ERROR!", JOptionPane.ERROR_MESSAGE);
				return false;
			}
			
			//MiSSING KEY:
			StringBuilder missingKey = new StringBuilder();
			missingKey.append("Cannot proceed to post this quiz! \nThe following questions are missing a key answer:\n\n");
			for(QuizQuestionComposerPanel question : listOfQuestionPanel){
				if(question.validateMissingKeySelection() == false){
					missingKey.append("   - Question #"+ question.questionIndex + "\n");
					validateResult = false;
				}
			}
			missingKey.append("\nPlease select a key answer for these questions.");
			if(validateResult == false){
				JOptionPane.showMessageDialog(CmsPresenter.mainView, missingKey.toString(), "ERROR!", JOptionPane.ERROR_MESSAGE);
				return false;
			}
			
			//INVALID OPTION:
			StringBuilder invalidOption = new StringBuilder();
			invalidOption.append("The following questions have options that are out of order:\n\n");
			for(QuizQuestionComposerPanel question : listOfQuestionPanel){
				if(question.validateMissingInBetweenOption() == false){
					invalidOption.append("   - Question #"+ question.questionIndex + "\n");
					validateResult = false;
				}
			}
			invalidOption.append("\nPlease fill the options in this order A, B, C, D, and then E.");
			if(validateResult == false){
				JOptionPane.showMessageDialog(CmsPresenter.mainView, invalidOption.toString(), "ERROR!", JOptionPane.ERROR_MESSAGE);
				return false;
			}
			return validateResult;
		}
		
	}
	
	
 	class NumQuestionChangeListener implements ChangeListener{

		@Override
		public void stateChanged(ChangeEvent e) {
			int numQuestion = (Integer) jsNumQuestion.getValue();
			int listSize = listOfQuestionPanel.size();
			
			if(numQuestion < listSize){
				//check list of question from index (numQuestion-1) to (listSize - 1) to see if questions are empty
				boolean emptyCheckResult = true;
				for (int i = listSize - 1; i >= numQuestion; i--){
					
					System.out.println("question " + i + " is Empty: " + listOfQuestionPanel.get(i).isEmpty());
					
					if(! listOfQuestionPanel.get(i).isEmpty()){ //one of the question is not empty
						emptyCheckResult = false;
						break;
					}
				}
				
				//if all empty, reduce number of list to numQuestion.
				if(emptyCheckResult == true){
					for (int i = listSize - 1; i >= numQuestion; i--){
						listOfQuestionPanel.remove(i);
					}
				}
				else{
					JOptionPane.showMessageDialog(CmsPresenter.mainView,
						    "The questions you want to remove are not empty!",
						    "ERROR!",
						    JOptionPane.ERROR_MESSAGE);
					jsNumQuestion.setValue(listSize);
				}
			}
			else if(numQuestion > listSize){
				for(int i = 0; i < (numQuestion - listSize);i++){
					listOfQuestionPanel.add(new QuizQuestionComposerPanel());
				}
			}
			
			//set the point per question:
			DecimalFormat df = new DecimalFormat("###.0");
			jsPointPerQuestion.setText(df.format(100.0d / listOfQuestionPanel.size()));
			
			
			displayListOfQuestion();
		}
		
	}
	
	class AddQuestionActionListener implements ActionListener{

		@Override
		public void actionPerformed(ActionEvent e) {
			int numQuestion = (Integer) jsNumQuestion.getValue();
			jsNumQuestion.setValue(++numQuestion);
		}
		
	}
	
	
	
	public class QuizQuestionComposerPanel extends JPanel{
		
		private int questionIndex = 0;
		
		private JTextArea jtfQuestion;
		
		private ButtonGroup bGroup;
		private JRadioButton jrbA;
		private JRadioButton jrbB;
		private JRadioButton jrbC;
		private JRadioButton jrbD;
		private JRadioButton jrbE;
		
		private JTextArea jtfA;
		private JTextArea jtfB;
		private JTextArea jtfC;
		private JTextArea jtfD;
		private JTextArea jtfE;
		List<JTextArea> listOfOptions;
		
		private JLabel jlQuestionNum;
		private JButton jbtClear;
		private JButton btnRemove;
		
		public QuizQuestionComposerPanel() {
			setBackground(Color.WHITE);
			GridBagLayout gridBagLayout = new GridBagLayout();
			setLayout(gridBagLayout);
			setOpaque(false);
			setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY));
			
			JPanel panel = new JPanel();
			panel.setOpaque(false);
			panel.setBorder(BorderFactory.createEmptyBorder());
			GridBagConstraints gbc_panel = new GridBagConstraints();
			gbc_panel.anchor = GridBagConstraints.LINE_START;
			gbc_panel.gridwidth = 2;
			gbc_panel.insets = new Insets(10, 10, 5, 10);
			gbc_panel.fill = GridBagConstraints.BOTH;
			gbc_panel.gridx = 0;
			gbc_panel.gridy = 0;
			add(panel, gbc_panel);
			GridBagLayout gbl_panel = new GridBagLayout();
			panel.setLayout(gbl_panel);
			
			JLabel jlQN = new JLabel("Question Number");
			jlQN.setFont(new Font("Lucida Grande", Font.BOLD, 15));
			GridBagConstraints gbc_jlQN = new GridBagConstraints();
			gbc_jlQN.anchor = GridBagConstraints.LINE_START;
			gbc_jlQN.insets = new Insets(0, 0, 0, 5);
			gbc_jlQN.gridx = 0;
			gbc_jlQN.gridy = 0;
			panel.add(jlQN, gbc_jlQN);
			
			jlQuestionNum = new JLabel("1");
			jlQuestionNum.setFont(new Font("Lucida Grande", Font.BOLD, 15));
			GridBagConstraints gbc_jlQuestionNum = new GridBagConstraints();
			gbc_jlQuestionNum.anchor = GridBagConstraints.LINE_START;
			gbc_jlQuestionNum.insets = new Insets(0, 0, 0, 5);
			gbc_jlQuestionNum.gridx = 1;
			gbc_jlQuestionNum.gridy = 0;
			panel.add(jlQuestionNum, gbc_jlQuestionNum);
			
			JLabel label = new JLabel(":");
			label.setFont(new Font("Lucida Grande", Font.BOLD, 15));
			GridBagConstraints gbc_label = new GridBagConstraints();
			gbc_label.insets = new Insets(0, 0, 0, 5);
			gbc_label.anchor = GridBagConstraints.LINE_START;
			gbc_label.gridx = 2;
			gbc_label.gridy = 0;
			panel.add(label, gbc_label);
			
			jbtClear = new JButton("Clear");
			jbtClear.setForeground(Color.BLUE);
			jbtClear.setOpaque(false);
			jbtClear.setBorder(BorderFactory.createEmptyBorder());
			GridBagConstraints gbc_jbtClear = new GridBagConstraints();
			gbc_jbtClear.anchor = GridBagConstraints.LINE_END;
			gbc_jbtClear.weightx = 1.0;
			gbc_jbtClear.insets = new Insets(0, 0, 0, 30);
			gbc_jbtClear.gridx = 3;
			gbc_jbtClear.gridy = 0;
			panel.add(jbtClear, gbc_jbtClear);
			
			btnRemove = new JButton("Remove");
			btnRemove.setForeground(Color.BLUE);
			btnRemove.setOpaque(false);
			btnRemove.setBorder(BorderFactory.createEmptyBorder());
			GridBagConstraints gbc_btnRemove = new GridBagConstraints();
			gbc_btnRemove.anchor = GridBagConstraints.LINE_END;
			gbc_btnRemove.gridx = 4;
			gbc_btnRemove.gridy = 0;
			panel.add(btnRemove, gbc_btnRemove);
			
			JLabel lblQuestion_1 = new JLabel("Question: ");
			lblQuestion_1.setFont(new Font("Lucida Grande", Font.BOLD, 13));
			GridBagConstraints gbc_lblQuestion_1 = new GridBagConstraints();
			gbc_lblQuestion_1.insets = new Insets(0, 10, 5, 5);
			gbc_lblQuestion_1.gridx = 0;
			gbc_lblQuestion_1.gridy = 1;
			add(lblQuestion_1, gbc_lblQuestion_1);
			
		    jtfQuestion = new JTextArea();
			jtfQuestion.setWrapStyleWord(true);
			jtfQuestion.setLineWrap(true);
			jtfQuestion.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
			JScrollPane jspQ = new JScrollPane(jtfQuestion);
			jspQ.setPreferredSize(new Dimension(400, 60));
			jspQ.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
			GridBagConstraints gbc_jtfQuestion = new GridBagConstraints();
			gbc_jtfQuestion.insets = new Insets(0, 0, 5, 10);
			gbc_jtfQuestion.fill = GridBagConstraints.BOTH;
			gbc_jtfQuestion.gridx = 1;
			gbc_jtfQuestion.gridy = 1;
			add(jspQ, gbc_jtfQuestion);
			
			jrbA = new JRadioButton("Option A: ");
			GridBagConstraints gbc_jrbA = new GridBagConstraints();
			gbc_jrbA.anchor = GridBagConstraints.LINE_START;
			gbc_jrbA.insets = new Insets(0, 10, 5, 5);
			gbc_jrbA.gridx = 0;
			gbc_jrbA.gridy = 2;
			add(jrbA, gbc_jrbA);
			
			jtfA = new JTextArea();
			jtfA.setWrapStyleWord(true);
			jtfA.setLineWrap(true);
			jtfA.setForeground(Color.DARK_GRAY);
			jtfA.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
			JScrollPane jspA = new JScrollPane(jtfA);
			jspA.setPreferredSize(new Dimension(400, 35));
			jspA.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
			GridBagConstraints gbc_jtfA = new GridBagConstraints();
			gbc_jtfA.insets = new Insets(0, 0, 5, 10);
			gbc_jtfA.fill = GridBagConstraints.HORIZONTAL;
			gbc_jtfA.gridx = 1;
			gbc_jtfA.gridy = 2;
			add(jspA, gbc_jtfA);
			jtfA.setColumns(10);
			
			
			jrbB = new JRadioButton("Option B: ");
			GridBagConstraints gbc_jrbB = new GridBagConstraints();
			gbc_jrbB.anchor = GridBagConstraints.LINE_START;
			gbc_jrbB.insets = new Insets(0, 10, 5, 5);
			gbc_jrbB.gridx = 0;
			gbc_jrbB.gridy = 3;
			add(jrbB, gbc_jrbB);
			
			jtfB = new JTextArea();
			jtfB.setWrapStyleWord(true);
			jtfB.setLineWrap(true);
			jtfB.setForeground(Color.DARK_GRAY);
			jtfB.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
			JScrollPane jspB = new JScrollPane(jtfB);
			jspB.setPreferredSize(new Dimension(400, 35));
			jspB.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
			GridBagConstraints gbc_jtfB = new GridBagConstraints();
			gbc_jtfB.insets = new Insets(0, 0, 5, 10);
			gbc_jtfB.fill = GridBagConstraints.HORIZONTAL;
			gbc_jtfB.gridx = 1;
			gbc_jtfB.gridy = 3;
			add(jspB, gbc_jtfB);
			jtfB.setColumns(10);
			
			jrbC = new JRadioButton("Option C: ");
			GridBagConstraints gbc_jrbC = new GridBagConstraints();
			gbc_jrbC.anchor = GridBagConstraints.LINE_START;
			gbc_jrbC.insets = new Insets(0, 10, 5, 5);
			gbc_jrbC.gridx = 0;
			gbc_jrbC.gridy = 4;
			add(jrbC, gbc_jrbC);
			
			jtfC = new JTextArea();
			jtfC.setLineWrap(true);
			jtfC.setWrapStyleWord(true);
			jtfC.setForeground(Color.DARK_GRAY);
			jtfC.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
			JScrollPane jspC = new JScrollPane(jtfC);
			jspC.setPreferredSize(new Dimension(400, 35));
			jspC.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
			GridBagConstraints gbc_jtfC = new GridBagConstraints();
			gbc_jtfC.insets = new Insets(0, 0, 5, 10);
			gbc_jtfC.fill = GridBagConstraints.HORIZONTAL;
			gbc_jtfC.gridx = 1;
			gbc_jtfC.gridy = 4;
			add(jspC, gbc_jtfC);
			jtfC.setColumns(10);
			
			jrbD = new JRadioButton("Option D: ");
			GridBagConstraints gbc_jrbD = new GridBagConstraints();
			gbc_jrbD.anchor = GridBagConstraints.LINE_START;
			gbc_jrbD.insets = new Insets(0, 10, 5, 5);
			gbc_jrbD.gridx = 0;
			gbc_jrbD.gridy = 5;
			add(jrbD, gbc_jrbD);
			
			jtfD = new JTextArea();
			jtfD.setLineWrap(true);
			jtfD.setWrapStyleWord(true);
			jtfD.setForeground(Color.DARK_GRAY);
			jtfD.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
			JScrollPane jspD = new JScrollPane(jtfD);
			jspD.setPreferredSize(new Dimension(400, 35));
			jspD.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
			GridBagConstraints gbc_jtfD = new GridBagConstraints();
			gbc_jtfD.insets = new Insets(0, 0, 5, 10);
			gbc_jtfD.fill = GridBagConstraints.HORIZONTAL;
			gbc_jtfD.gridx = 1;
			gbc_jtfD.gridy = 5;
			add(jspD, gbc_jtfD);
			jtfD.setColumns(10);
			
			jrbE = new JRadioButton("Option E: ");
			GridBagConstraints gbc_jrbE = new GridBagConstraints();
			gbc_jrbE.anchor = GridBagConstraints.LINE_START;
			gbc_jrbE.insets = new Insets(0, 10, 10, 5);
			gbc_jrbE.gridx = 0;
			gbc_jrbE.gridy = 6;
			add(jrbE, gbc_jrbE);
			
			jtfE = new JTextArea();
			jtfE.setWrapStyleWord(true);
			jtfE.setLineWrap(true);
			jtfE.setForeground(Color.DARK_GRAY);
			jtfE.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
			JScrollPane jspE = new JScrollPane(jtfE);
			jspE.setPreferredSize(new Dimension(400, 35));
			jspE.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
			GridBagConstraints gbc_jtfE = new GridBagConstraints();
			gbc_jtfE.insets = new Insets(0, 0, 10, 10);
			gbc_jtfE.fill = GridBagConstraints.HORIZONTAL;
			gbc_jtfE.gridx = 1;
			gbc_jtfE.gridy = 6;
			add(jspE, gbc_jtfE);
			jtfE.setColumns(10);
			
			bGroup = new ButtonGroup();
			bGroup.add(jrbA);
			bGroup.add(jrbB);
			bGroup.add(jrbC);
			bGroup.add(jrbD);
			bGroup.add(jrbE);
			
			listOfOptions = new ArrayList();
			listOfOptions.add(jtfA);
			listOfOptions.add(jtfB);
			listOfOptions.add(jtfC);
			listOfOptions.add(jtfD);
			listOfOptions.add(jtfE);
			
			//DEFAULT:
			jtfA.setEnabled(false);
			jrbA.setEnabled(false);
			jtfB.setEnabled(false);
			jrbB.setEnabled(false);
			jtfC.setEnabled(false);
			jrbC.setEnabled(false);
			jtfD.setEnabled(false);
			jrbD.setEnabled(false);
			jtfE.setEnabled(false);
			jrbE.setEnabled(false);
			
			//ACTION LISTENER:
			jbtClear.addActionListener(new ActionListener(){

				@Override
				public void actionPerformed(ActionEvent e) {
					clearContent();
				}
				
			});
			
			btnRemove.addActionListener(new ActionListener(){

				@Override
				public void actionPerformed(ActionEvent e) {
					listOfQuestionPanel.remove(questionIndex-1);
					jsNumQuestion.setValue((Integer) listOfQuestionPanel.size()); 
					displayListOfQuestion();
				}
				
			});
			
			//ACTION LISTENERS: Text change
			jtfQuestion.getDocument().addDocumentListener(new QuestionEmptyListener());
			jtfA.getDocument().addDocumentListener(new OptAEmptyListener());
			jtfB.getDocument().addDocumentListener(new OptBEmptyListener());
			jtfC.getDocument().addDocumentListener(new OptCEmptyListener());
			jtfD.getDocument().addDocumentListener(new OptDEmptyListener());
			jtfE.getDocument().addDocumentListener(new OptEEmptyListener());
		}
		
		public boolean validateSameOptionContent(){
			if(validateMissingAllOptions()){
				for(int i=0; i< listOfOptions.size();i++){
					String curOpt = listOfOptions.get(i).getText().trim();
					if(curOpt.equals("") == false){//only compare non-empty textfield
						for(int j = i+1; j < listOfOptions.size(); j++){
							String compOptString = listOfOptions.get(j).getText().trim();
							if(compOptString.equals("") == false && curOpt.equals(compOptString)){
								System.err.println("ERROR: Same option for Question#" + questionIndex);
								return false; //if found repeated option, return false
							}
						}
					}
				}
				return true;
			}
			else return false;
		}
		
		public boolean validateMissingInBetweenOption(){
			if(validateMissingAllOptions()){	
				for(int i = listOfOptions.size() - 1; i >= 0 ;i--){
					String curOpt = listOfOptions.get(i).getText().trim();
					if(!curOpt.equals("")){ //if current Opt is not empty
						for(int j = i-1; j >=0; j--){//check the upper option if they are empty
							String compOptString = listOfOptions.get(j).getText().trim();
							if(compOptString.equals("")){
								System.err.println("ERROR: Missing in between option for Question#" + questionIndex);
								return false; //if found empty option, return false
							}
						}
					}
				}
				return true;
			}
			else{
				
				return false;
			}
		}
		
		public boolean validateMissingQuestion(){
			if(jtfQuestion.getText().trim().equals("")){
				System.err.println("ERROR: Missing question for Question#" + questionIndex);
				return false; //empty question
			}
			else return true;
		}
		
		public boolean validateMissingAllOptions(){
			boolean result = true;
			
			for(int i=0; i< listOfOptions.size();i++){
				String curOpt = listOfOptions.get(i).getText().trim();
				result &= curOpt.equals("");
			}
			
			if(result){
				System.err.println("ERROR: Missing all options for Question#" + questionIndex);
			}
			return !result;
		}
		
		public boolean validateMissingKeySelection(){
			boolean result = true;
			
			result = (jrbA.isSelected() & jrbA.isEnabled())
					| (jrbB.isSelected() & jrbB.isEnabled())
					| (jrbC.isSelected() & jrbC.isEnabled())
					| (jrbD.isSelected() & jrbD.isEnabled())
					| (jrbE.isSelected() & jrbE.isEnabled());
			return result;
		}
		
		public char getSelectedKey(){
			
				if(jrbA.isSelected()) return 'A';
				if(jrbB.isSelected()) return 'B';
				if(jrbC.isSelected()) return 'C';
				if(jrbD.isSelected()) return 'D';
				if(jrbE.isSelected()) return 'E';
				return '0';

		}
		
		public List<String> getInputtedOption(){
			List<String> returnList = new ArrayList();
			if(jtfA.isEnabled() & jrbA.isEnabled()){
				returnList.add(jtfA.getText().trim());
			} else return returnList; //if an upper option is not enabled, ignore the rest;
			if(jtfB.isEnabled() & jrbB.isEnabled()){
				returnList.add(jtfB.getText().trim());
			} else return returnList; //if an upper option is not enabled, ignore the rest;
			if(jtfC.isEnabled() & jrbC.isEnabled()){
				returnList.add(jtfC.getText().trim());
			} else return returnList; //if an upper option is not enabled, ignore the rest;
			if(jtfD.isEnabled() & jrbD.isEnabled()){
				returnList.add(jtfD.getText().trim());
			} else return returnList; //if an upper option is not enabled, ignore the rest;
			if(jtfE.isEnabled() & jrbE.isEnabled()){
				returnList.add(jtfE.getText().trim());
			} else return returnList; //if an upper option is not enabled, ignore the rest;
			return returnList;
		}
		
		public CmsQuizQuestion getSelectedQuizQuestion(){
			int questionID = 0;
			String question = jtfQuestion.getText().trim();
			char key = getSelectedKey();
			List<String> options = getInputtedOption();
			
			return new CmsQuizQuestion(questionID, question, key, options);
		}
		
		
		private class QuestionEmptyListener implements DocumentListener{
			
			@Override
			public void insertUpdate(DocumentEvent e) {
				changed();
			}

			@Override
			public void removeUpdate(DocumentEvent e) {
				changed();
			}

			@Override
			public void changedUpdate(DocumentEvent e) {
				changed();
			}
			
			public void changed(){
				if(jtfQuestion.getText().trim().equals("")){
					jtfA.setEnabled(false);
					jrbA.setEnabled(false);
					jtfB.setEnabled(false);
					jrbB.setEnabled(false);
					jtfC.setEnabled(false);
					jrbC.setEnabled(false);
					jtfD.setEnabled(false);
					jrbD.setEnabled(false);
					jtfE.setEnabled(false);
					jrbE.setEnabled(false);
				}
				else{
					jtfA.setEnabled(true);
					
					if(!jtfA.getText().trim().equals("")){
						jtfA.setEnabled(true);
						jrbA.setEnabled(true);
						jtfB.setEnabled(true);
						if(!jtfB.getText().trim().equals("")){
							jtfB.setEnabled(true);
							jrbB.setEnabled(true);
							jtfC.setEnabled(true);
							if(!jtfC.getText().trim().equals("")){
								jtfC.setEnabled(true);
								jrbC.setEnabled(true);
								jtfD.setEnabled(true);
								if(!jtfD.getText().trim().equals("")){
									jtfD.setEnabled(true);
									jrbD.setEnabled(true);
									jtfE.setEnabled(true);
									if(!jtfE.getText().trim().equals("")){
										jtfE.setEnabled(true);
										jrbE.setEnabled(true);
									}
								}
							}
						}
					}
					
				}
			}
		}
		
		private class OptAEmptyListener implements DocumentListener{
			
			@Override
			public void insertUpdate(DocumentEvent e) {
				changed();
			}

			@Override
			public void removeUpdate(DocumentEvent e) {
				changed();
			}

			@Override
			public void changedUpdate(DocumentEvent e) {
				changed();
			}
			
			public void changed(){
				if(jtfA.getText().trim().equals("")){
					jrbA.setEnabled(false);
					jtfB.setEnabled(false);
					jrbB.setEnabled(false);
					jtfC.setEnabled(false);
					jrbC.setEnabled(false);
					jtfD.setEnabled(false);
					jrbD.setEnabled(false);
					jtfE.setEnabled(false);
					jrbE.setEnabled(false);
				}
				else{
					jrbA.setEnabled(true);
					jtfB.setEnabled(true);
					
					if(!jtfA.getText().trim().equals("")){
						jtfA.setEnabled(true);
						jrbA.setEnabled(true);
						if(!jtfB.getText().trim().equals("")){
							jtfB.setEnabled(true);
							jrbB.setEnabled(true);
							if(!jtfC.getText().trim().equals("")){
								jtfC.setEnabled(true);
								jrbC.setEnabled(true);
								if(!jtfD.getText().trim().equals("")){
									jtfD.setEnabled(true);
									jrbD.setEnabled(true);
									if(!jtfE.getText().trim().equals("")){
										jtfE.setEnabled(true);
										jrbE.setEnabled(true);
									}
								}
							}
						}
					}
				}
			}
		}
		
		private class OptBEmptyListener implements DocumentListener{
			
			@Override
			public void insertUpdate(DocumentEvent e) {
				changed();
			}

			@Override
			public void removeUpdate(DocumentEvent e) {
				changed();
			}

			@Override
			public void changedUpdate(DocumentEvent e) {
				changed();
			}
			
			public void changed(){
				if(jtfB.getText().trim().equals("")){
					jrbB.setEnabled(false);
					jtfC.setEnabled(false);
					jrbC.setEnabled(false);
					jtfD.setEnabled(false);
					jrbD.setEnabled(false);
					jtfE.setEnabled(false);
					jrbE.setEnabled(false);
				}
				else{
					jrbB.setEnabled(true);
					jtfC.setEnabled(true);
					
					if(!jtfA.getText().trim().equals("")){
						jtfA.setEnabled(true);
						jrbA.setEnabled(true);
						jtfB.setEnabled(true);
						if(!jtfB.getText().trim().equals("")){
							jtfB.setEnabled(true);
							jrbB.setEnabled(true);
							jtfC.setEnabled(true);
							if(!jtfC.getText().trim().equals("")){
								jtfC.setEnabled(true);
								jrbC.setEnabled(true);
								jtfD.setEnabled(true);
								if(!jtfD.getText().trim().equals("")){
									jtfD.setEnabled(true);
									jrbD.setEnabled(true);
									jtfE.setEnabled(true);
									if(!jtfE.getText().trim().equals("")){
										jtfE.setEnabled(true);
										jrbE.setEnabled(true);
									}
								}
							}
						}
					}
				}
			}
		}
		
		private class OptCEmptyListener implements DocumentListener{
			
			@Override
			public void insertUpdate(DocumentEvent e) {
				changed();
			}

			@Override
			public void removeUpdate(DocumentEvent e) {
				changed();
			}

			@Override
			public void changedUpdate(DocumentEvent e) {
				changed();
			}
			
			public void changed(){
				if(jtfC.getText().trim().equals("")){
					jrbC.setEnabled(false);
					jtfD.setEnabled(false);
					jrbD.setEnabled(false);
					jtfE.setEnabled(false);
					jrbE.setEnabled(false);
				}
				else{
					jrbC.setEnabled(true);
					jtfD.setEnabled(true);
					
					if(!jtfA.getText().trim().equals("")){
						jtfA.setEnabled(true);
						jrbA.setEnabled(true);
						jtfB.setEnabled(true);
						if(!jtfB.getText().trim().equals("")){
							jtfB.setEnabled(true);
							jrbB.setEnabled(true);
							jtfC.setEnabled(true);
							if(!jtfC.getText().trim().equals("")){
								jtfC.setEnabled(true);
								jrbC.setEnabled(true);
								jtfD.setEnabled(true);
								if(!jtfD.getText().trim().equals("")){
									jtfD.setEnabled(true);
									jrbD.setEnabled(true);
									jtfE.setEnabled(true);
									if(!jtfE.getText().trim().equals("")){
										jtfE.setEnabled(true);
										jrbE.setEnabled(true);
									}
								}
							}
						}
					}
				}
			}
		}
		
		private class OptDEmptyListener implements DocumentListener{
			
			@Override
			public void insertUpdate(DocumentEvent e) {
				changed();
			}

			@Override
			public void removeUpdate(DocumentEvent e) {
				changed();
			}

			@Override
			public void changedUpdate(DocumentEvent e) {
				changed();
			}
			
			public void changed(){
				if(jtfQuestion.getText().trim().equals("")){
					jrbD.setEnabled(false);
					jtfE.setEnabled(false);
					jrbE.setEnabled(false);
				}
				else{
					jrbD.setEnabled(true);
					jtfE.setEnabled(true);
					
					if(!jtfA.getText().trim().equals("")){
						jtfA.setEnabled(true);
						jrbA.setEnabled(true);
						jtfB.setEnabled(true);
						if(!jtfB.getText().trim().equals("")){
							jtfB.setEnabled(true);
							jrbB.setEnabled(true);
							jtfC.setEnabled(true);
							if(!jtfC.getText().trim().equals("")){
								jtfC.setEnabled(true);
								jrbC.setEnabled(true);
								jtfD.setEnabled(true);
								if(!jtfD.getText().trim().equals("")){
									jtfD.setEnabled(true);
									jrbD.setEnabled(true);
									jtfE.setEnabled(true);
									if(!jtfE.getText().trim().equals("")){
										jtfE.setEnabled(true);
										jrbE.setEnabled(true);
									}
								}
							}
						}
					}
				}
			}
		}
		
		private class OptEEmptyListener implements DocumentListener{
			
			@Override
			public void insertUpdate(DocumentEvent e) {
				changed();
			}

			@Override
			public void removeUpdate(DocumentEvent e) {
				changed();
			}

			@Override
			public void changedUpdate(DocumentEvent e) {
				changed();
			}
			
			public void changed(){
				if(jtfE.getText().trim().equals("")){
					jrbE.setEnabled(false);
				}
				else{
					jrbE.setEnabled(true);
					
					if(!jtfA.getText().trim().equals("")){
						jtfA.setEnabled(true);
						jrbA.setEnabled(true);
						jtfB.setEnabled(true);
						if(!jtfB.getText().trim().equals("")){
							jtfB.setEnabled(true);
							jrbB.setEnabled(true);
							jtfC.setEnabled(true);
							if(!jtfC.getText().trim().equals("")){
								jtfC.setEnabled(true);
								jrbC.setEnabled(true);
								jtfD.setEnabled(true);
								if(!jtfD.getText().trim().equals("")){
									jtfD.setEnabled(true);
									jrbD.setEnabled(true);
									jtfE.setEnabled(true);
									if(!jtfE.getText().trim().equals("")){
										jtfE.setEnabled(true);
										jrbE.setEnabled(true);
									}
								}
							}
						}
					}
				}
			}
		}

		public boolean isEmpty(){
			
			if(! (jtfQuestion.getText().equals(""))) return false;
			if(! (jtfA.getText().equals(""))) return false;
			if(! (jtfB.getText().equals(""))) return false;
			if(! (jtfC.getText().equals(""))) return false;
			if(! (jtfD.getText().equals(""))) return false;
			if(! (jtfE.getText().equals(""))) return false;
			return true;
		}
		
		public void setQuestionNumber(int num){
			questionIndex = num;
			jlQuestionNum.setText("" + num);
		}
		
		public void clearContent(){
			jtfQuestion.setText("");
			jtfA.setText("");
			jtfB.setText("");
			jtfC.setText("");
			jtfD.setText("");
			jtfE.setText("");
			
			bGroup.clearSelection();
		}

	}

}	

